package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.TaskTypeEnum;
import com.heima.model.schedule.dtos.Task;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.ProtostuffUtil;
import com.heima.wemedia.service.WmNewsTaskService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.Date;

@Service
@Slf4j//SLF4J日志框架记录日志
public class WmNewsTaskServiceImpl implements WmNewsTaskService {


	@Autowired
	private IScheduleClient scheduleClient;

	/**
	 * 添加任务到延迟队列中
	 *
	 * @param id          文章的id
	 * @param publishTime 文章发布的时间  可以做为任务的执行时间
	 */
	@Override
	@Async//表示该方法是一个异步方法，即调用该方法时会立即返回，而方法的实际执行会在后台线程中进行
	public void addNewsToTask(Integer id, Date publishTime) {

		log.info("添加任务到延迟服务中----begin");

		//创建一个 Task 对象，用于表示将要添加到延迟队列中的任务
		Task task = new Task();
		task.setExecuteTime(publishTime.getTime());//设置任务的执行时间的毫秒值
		//设置任务的类型和优先级
		task.setTaskType(TaskTypeEnum.NEWS_SCAN_TIME.getTaskType());
		task.setPriority(TaskTypeEnum.NEWS_SCAN_TIME.getPriority());
		//设置任务的参数，这里的参数是文章的id，用于后续查询文章的详细信息
		WmNews wmNews = new WmNews();
		wmNews.setId(id);
		//这里调用了工具类ProtostuffUtil将wmNews进行了序列化,以便将文章信息作为任务的参数传递给调度系统
		task.setParameters(ProtostuffUtil.serialize(wmNews));

		scheduleClient.addTask(task);

		log.info("添加任务到延迟服务中----end");

	}

	@Autowired
	private WmNewsAutoScanServiceImpl wmNewsAutoScanService;

	/**
	 * 消费延迟队列数据
	 */
	@Scheduled(fixedRate = 1000)//表示该方法每隔1000毫秒执行一次，每秒拉取一次任务队列
	@Override
	@SneakyThrows//用于在方法签名中隐藏受检异常（checked exceptions）,在该方法中，使用了此注解来简化异常处理
	public void scanNewsByTask() {

		log.info("文章审核---消费任务执行---begin---");

		//通过scheduleClient从调度系统中拉取任务,poll方法接受任务类型和优先级作为参数，用于指定要拉取的任务队列
		ResponseResult responseResult = scheduleClient.poll(TaskTypeEnum.NEWS_SCAN_TIME.getTaskType(), TaskTypeEnum.NEWS_SCAN_TIME.getPriority());
		//检查从调度系统拉取任务的结果
		//responseResult.getCode()返回响应的状态码，responseResult.getData()返回任务的详细信息
		//如果状态码为200（表示成功）并且数据不为空，则继续执行后续操作
		if(responseResult.getCode().equals(200) && responseResult.getData() != null){
			//将响应结果中的数据转换为JSON字符串
			String json_str = JSON.toJSONString(responseResult.getData());
			//将JSON字符串反序列化为Task对象
			Task task = JSON.parseObject(json_str, Task.class);
			//从Task对象中获取参数，这些参数是序列化后的文章信息
			byte[] parameters = task.getParameters();
			//这里调用了工具类ProtostuffUtil将参数反序列化，得到文章的id，并调用文章审核的方法进行审核
			WmNews wmNews = ProtostuffUtil.deserialize(parameters, WmNews.class);
			System.out.println(wmNews.getId()+"-----------");
			//调用wmNewsAutoScanService中的autoScanWmNews方法，对文章进行自动审核
			wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
		}
		log.info("文章审核---消费任务执行---end---");
	}
}
